#ifndef IMGPROVIDER_H
#define IMGPROVIDER_H

#include <QDebug>
#include "src/pubimp.h"
#include "src/Manager/ThreadPool.h"
#include "src/device/Camera/camerahelper.h"
#include "src/device/Robot/robothelper.h"
#include "src/device/Machine/MachineHelper.h"
#include "MU_ExpMessage.h"
#include "base/data_types.h"
#include "src/define/func_define.h"
#include "src/SoftWare/DateTime/DateTime.h"
#include "src/SoftWare/Log/LogHelper.h"
#include "src/device/Laser/laserhelper.h"
#include "src/device/PLC/PLCHelper.h"
#include <future>
#include "getuvonshell/getsbuva.h"
#include "base/fitCorrelation.h"
#include <functional>
#include "src/SoftWare/Thread/DequeThread.h"

/*******************************************************************************/
//  参数
typedef std::tuple<double,double,string> ImagePara;     /// 先定义图像算法的参数
typedef std::tuple<double,double,string> ImageResult;     /// 先定义图像算法的参数
/*******************************************************************************/


/*******************************************************************************/
//  每一条运行时的数据
typedef std::tuple<cv::Mat,RobotPos,UV,std::string> Image_Run_Data;     /// 0.图像  1.Pos  2.UV 3.时间


/*******************************************************************************/

class ImgProvider
{
public:
    ImgProvider();

    static ImgProvider* GetInstance(){
        static QMutex mutex;
        static QScopedPointer<ImgProvider> inst;
        if (Q_UNLIKELY(!inst)) {
            mutex.lock();
            if (!inst) {
                inst.reset(new ImgProvider);
            }
            mutex.unlock();
        }
        return inst.data();
    }



    boost::signals2::signal<void(PMsg)> reflushMsg;     // 反馈当前进度

    /**
     * @brief callImagePoss
     * @param string 当前文件夹的名字
     * @param poss      一组格点包
     * @param correct       无意义暂时
     * @details 输入一组格点，间隔的进行拍图,去一个点停一下然后拍照
     */
    void callImagePoss(string ,GenPosVector &poss,bool correct = false);

    // 输入一组格点，分为2个线程，一个负责运动一个负责保存
    void callImageConPoss(string ,GenPosVector &poss);

    // 从一组格点中找到真实的Robotos
    std::pair<RobotPos,RobotPos> findRealPos(GenPosVector &poss);
    /// 定时,只拍图
    void callTackPic(){
        try {
            auto result = std::async(std::launch::async,[](){
                  std::vector<cv::Mat> vct;
                  cv::Mat mat = CameraHelper::GetInstance()->GetPictrue();
                  vct.push_back(mat);
                  sleep_ms(50);
                  return  vct;
                  /// Log写图像
            });
            std::vector<cv::Mat> vct = result.get();
            auto save = std::async(std::launch::async,[&vct](){
                static int start = 0;
                for(auto d:vct){
                    /// log 保存图像
                    /// 创建当前时间的文件夹
                    /// 命名规则
                    /// tostring(start)
                    string f = "path" + std::to_string(start);
                    cv::imwrite(f,d);
                    start++;
                }
            });
            save.get();

        }catch(MU_EXPS::CAMERA_EXPECTION e){
            /// 写入日志
            qWarning()<<"相机采集数据失败!"<<__FUNCTION__;
            pushExp(MU_Messages::Camera,e,MU_ERROR_MODULE_CAM,DateTime::getFullTime());
        }
    }


    /// 使用相机
    /// ImagePara parament;
    /// ImageResult ret = callImageProcess<ImageResult,ImagePara>(mat,parament);
    template<typename R,typename T>
    R callImageProcess(T &t){
        try {
            auto result = std::async(std::launch::async,[=](){
                cv::Mat mat = CameraHelper::GetInstance()->GetPictrue();
                   /// R ret = XXXXX(mat,t);
            },this);
            return result.get_future().get();
        }catch(MU_EXPS::CAMERA_EXPECTION e){
            /// 写入日志
            qWarning("相机采集数据失败!",__FUNCTION__);
            pushExp(MU_Messages::Camera,e,MU_ERROR_MODULE_CAM,DateTime::getFullTime());
        }
        catch (...) {
            /// 写入日志
            qWarning("图像算法调用失败!",__FUNCTION__);
            throw MU_EXPS::EXP_IMAGE_IMAGE_FAIL;
            pushExp(MU_Messages::Image,MU_EXPS::EXP_IMAGE_IMAGE_FAIL,MU_ERROR_MODULE_IMAGE,DateTime::getFullTime());
            return *(new R);
        }
    }





private:
    /// 初始化后台线程
    void initBackThread();

    std::atomic<bool> isRun = ATOMIC_FLAG_INIT;
    std::deque<Image_Run_Data> dequeData;
    std::mutex g_mtx;
    std::condition_variable g_CV;
    GetSBuvA *_gxA;

    DequeThread *deqT;
};

#endif // IMGPROVIDER_H
